package com.xb.cloud.gateway.core.engine;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xb.cloud.gateway.client.Adapter;
import com.xb.cloud.gateway.client.Context;
import com.xb.cloud.gateway.client.Context.TimeLine;
import com.xb.cloud.gateway.client.RtnCodes;
import com.xb.cloud.gateway.core.BuildXBContext;
import com.xb.cloud.gateway.core.RtnInfoCreater;
import com.xb.cloud.gateway.filter.InboundFilter;
import com.xb.cloud.gateway.handler.LogHandler;
import com.xb.cloud.gateway.handler.ResponseRtnHandler;
import com.xb.cloud.gateway.utils.WebUtil;

/**
 * 
 * @ClassName: XBEngineImpl
 * @Description: 服务主引擎实现类 引擎负责主流程实现 ：适配器匹配获取、可以定义入流链和出流链，用于对数据的控制。
 * @author: 鲜备科技
 * @date: 2017年12月18日 下午4:11:44
 * 
 * @Copyright: 2017 www.xianbeitech.com Inc. All rights reserved.
 *
 */
@Component("xbEngineImpl")
public class XBEngineImpl {

	/**
	 * 适配器匹配调度执行对象（用于适配器装配、匹配及调度执行）
	 */
	@Autowired
	private XBDispatcher dispatcher;
	/**
	 * 后置处理器
	 */
	@Autowired
	private ResponseRtnHandler responseRtnHandler;

	@Resource
	InboundFilter inboundFilter;
	@Autowired
	private LogHandler logHandler;

	/**
	 * 
	 * @Title: init @Description: 初始化引擎 @param: @return: void @throws
	 */
	public void init() {
		dispatcher.init();
	}

	/**
	 * 
	 * @Title: execute @Description: 服务引擎执行方法 @param: @param req @param: @param
	 *         resp @return: void @throws
	 */
	public void execute(HttpServletRequest req, HttpServletResponse resp) {
		/*******************************
		 * app请求url 处理 用于匹配适配器
		 *********************************/
		// app请求路径
		String urlPath = req.getRequestURI();
		// 通过url匹配适配器并实例化适配器对象
		Adapter adapter = dispatcher.getAdapter(urlPath);

		// 适配器是否需要检查用户登录令牌
		Boolean isCheckToken = adapter != null ? adapter.isCheckUserToken() : false;
		/*******************************
		 * 适配器匹配 & 上下文构造
		 ****************************************/
		// 创建上线文对象
		Context xbContext = new Context(req, resp, urlPath, isCheckToken, new TimeLine(System.currentTimeMillis()),
				WebUtil.getClientIP(req), RtnInfoCreater.RightWlRtnInfo());

		// 进一步包装上线文对象，将request对象的parameter和header信息构造到上线文对象中
		BuildXBContext.execute(xbContext);

		// 未成功匹配适配器 将错误信息设置到上下文对象中
		if (adapter == null) {
			xbContext.setRtnInfo(RtnInfoCreater.CannotFindAdapter(xbContext.getUrlPath()));
		} else {
			// 入流程控制链 在主服务引擎 spring中设值注入
			/****************************************
			 * 入流程控制链服务执行 & 适配器执行
			 ********************************/

			// 入流程控制链
			inboundFilter.doFilter(xbContext, null);

			if (RtnCodes.SUCCESS.equalsIgnoreCase(xbContext.getRtnInfo().getRtnCode())) {
				xbContext.getTimeLine().setServiceRequestTime(System.currentTimeMillis());// 保存调用时间和返回时间
				dispatcher.execute(xbContext, adapter);// 执行adapter
				xbContext.getTimeLine().setServiceResponseTime(System.currentTimeMillis());
			}

			// 入流程控制链 执行过程中未出现异常 或 条件允许的前提下 执行结果正常
			// TODO：出流程控制
		}
		// TODO:日志处理后续改为异步处理
		logHandler.execute(xbContext);
		responseRtnHandler.execute(xbContext);

	}

}
